package top.shiyiri.stream;

import org.junit.Test;

import java.io.*;

/**
 * @author Aunean
 * @date 2022/1/9
 */
/*
一、流的分类：
1.操作数据单位：字节流、字符流
2.数据的流向：输入流、输出流
3.流的角色：节点流、处理流

二、流的体系结构
抽象基类            节点流（或文件流）                                   缓冲流（处理流的一种）
InputStream         FileInputStream (read(byte[] buffer))               BufferedInputStream (read(byte[] buffer))
OutputStream        FileOutputStream (write(byte[] buffer, 0, len))     BufferedOutputStream (write(byte[] buffer, 0, len))
Reader              FileReader (read(char[] cbuf))                      BufferedReader (read(char[] cbuf) / readLine())
Writer              FileWriter (write(char[] cbuf, 0, len))             BufferedWriter (write(char[] cbuf, 0, len))

 */
public class FileReaderWriterTest {

    /*
    输出 hello.txt 文件的内容
    1.read()的理解：返回读入的一个字符。如果达到文件末尾，返回 -1
    2.异常的处理：为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally处理
    3.读入的文件一定要存在，否则会报FileNotFoundException
     */
    @Test
    public void fileReaderTest() {
        //1.实例化 File 类的对象，指明要操作的文件
        File file = new File("hello.txt");
        //2.提供具体的流
        FileReader fileReader = null;
        try {
            fileReader = new FileReader(file);
            //3.数据的读入
//            int read = fileReader.read();
//            while (read != -1) {
//                System.out.print((char) read);
//                read = fileReader.read();
//            }
            int data;
            while ((data = fileReader.read()) != -1) {
                System.out.print((char)data);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流
            try {
                assert fileReader != null;
                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //对read()操作升级：使用read的重载方法
    @Test
    public void testFileReader1() {
        //1.File类的实例化
        File file = new File("hello.txt");
        FileReader reader = null;
        try {
            //2.FileReader流的实例化
            reader = new FileReader(file);
            //3.读入的操作
            //read(char[] cbuf)：返回每次读入cbuf数组中的字符的个数。如果达到文件末尾，返回 -1
            char[] cbuf = new char[5];
            int len;
            while ((len = reader.read(cbuf)) != -1) {
                //方式一
//                for (int i = 0; i < len; i++) {
//                    System.out.print(cbuf[i]);
//                }

                //方式二
                //错误的写法
//                String str = new String(cbuf);
//                System.out.print(str);
                //正确的写法
                String str2 = new String(cbuf, 0, len);
                System.out.print(str2);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流
            try {
                assert reader != null;
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /*
    从内存中写出数据到硬盘的文件中

    说明：
    1.输出操作，对应的File可以不存在
    2.File对应的硬盘中的文件如果不存在，则会自动创建此文件
        如果存在：
            如果流使用的构造器是：FileWriter(file, false) / FileWriter(file)：对原有文件进行覆盖
            如果流使用的构造器是：FileWriter(file, true)： 对原有文件进行追加
     */
    @Test
    public void fileWriterTest() {
        //1.提供File类的对象，指明写出到的文件
        File file = new File("hello2.txt");
        FileWriter fileWriter = null;

        try {
            //2.提供FileWriter的对象，用于数据的写出
            fileWriter = new FileWriter(file, false);

            //3.写出的操作
            fileWriter.write("HelloWorld\n");
            fileWriter.write("Hello Java");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流
            try {
                assert fileWriter != null;
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void testFileReaderFileWriter() {
        //1.创建File类的对象，指明读入和写出的文件
        File inputFile = new File("hello.txt");
        File outputFile = new File("hello_copy.txt");
        FileReader fileReader = null;
        FileWriter fileWriter = null;

        try {
            //2.创建FileReader类和FileWriter类的对象
            fileReader = new FileReader(inputFile);
            fileWriter = new FileWriter(outputFile);

            //3.数据的读入和写出操作
            char[] cbuf = new char[5];
            int len;//记录每次读入cbuf数组中的字符的个数
            while ((len = fileReader.read(cbuf)) != -1) {
                //每次写入len个字符
                fileWriter.write(cbuf, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流
            try {
                assert fileWriter != null;
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
